﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DNA.Mvc.jQuery
{
    [Serializable]
    public class QueryParams
    {
        private int pageSize = 20;
        private int pageIndex = 1;

        public string OrderBy { get; set; }

        public string GroupBy { get; set; }

        public string Filter { get; set; }

        public int Index
        {
            get { return pageIndex; }
            set { pageIndex = value; }
        }

        public int Size
        {
            get { return pageSize; }
            set { pageSize = value; }
        }

        public string GenerateOrderByExpression()
        {
            var fields = GetSortingFields();
            var ordered = new List<string>();
            
            if (fields != null)
            {
                for (int i = 0; i < fields.Length; i++)
                {
                    if (GetSortingOrder(fields[i]) == SortingOrders.Asc)
                        ordered.Add("it." + fields[i].Split('~')[0]);
                    else
                        ordered.Add("it." + fields[i].Split('~')[0] + " desc");
                }
                if (ordered.Count > 0)
                    return string.Join(",", ordered.ToArray());
            }
            return "";
        }

        /// <summary>
        /// Convert the querstring filter field to filter expression format.
        /// </summary>
        /// <returns></returns>
        public string GetFilterExpression()
        {
            if (!string.IsNullOrEmpty(Filter))
            {
                var filterExprs=Filter.Split('-');
                var exprs = new List<string>();

                foreach (var expr in filterExprs)
                {
                    var fieldName= expr.Split('~')[0];
                    exprs.Add("("+ expr.Replace(fieldName, "it." + fieldName)+")");
                }

                string result = string.Join(" && ", exprs.ToArray());
                result = result.Replace("~lt~", "<")
                    .Replace("~gt~", ">")
                    .Replace("~le~", "<=")
                    .Replace("~ge~", ">=")
                    .Replace("~eq~", "=")
                    .Replace("~neq~", "<>")
                    .Replace("~startswith~", " like ")
                    .Replace("~endswith~", " like ")
                    .Replace("~contains~", " like ")
                    .Replace("~and~", " and ")
                    .Replace("~or~", " or ")
                    .Replace("~not~", " not ");
                return result;
            }
            return "";
        }

        public List<FilterExpression> GetFilterExpressions()
        {
            var exprs = new List<FilterExpression>();

            if (!string.IsNullOrEmpty(Filter))
            {
                var filterExprs = Filter.Split('-');
                for (int i = 0; i < filterExprs.Length; i++)
                {
                    exprs.Add(new FilterExpression(filterExprs[i]));
                }
            }

            return exprs;
        }

        public string[] GetSortingFields()
        {
            if (!string.IsNullOrEmpty(OrderBy))
            {
                return OrderBy.Split(new char[] { '-' });
            }
            else
                return null;
        }

        public SortingOrders GetSortingOrder(string expr)
        {
            var sortingParams = expr.Split(new char[] { '~' });
            if (sortingParams.Count() == 2)
                return string.IsNullOrEmpty(sortingParams[1]) ? SortingOrders.Asc : (sortingParams[1].Equals("asc", StringComparison.OrdinalIgnoreCase) ? SortingOrders.Asc : SortingOrders.Desc);
            else
                return SortingOrders.NotSet;
        }

        public int GetZeroBaseIndex()
        {
            return Index == 0 ? Index : Index - 1;
        }

        public string[] GetGroupByFields()
        {
            if (!string.IsNullOrEmpty(GroupBy))
            {
                var _fieldArgs = GroupBy.Split(new char[] { '-' });
                return _fieldArgs;
            }
            return null;
        }

        public int GetSkipRecordCount(bool? isZeroBase=false)
        {
            if (isZeroBase.Value)
                return GetZeroBaseIndex() * Size;
            else
                return Index * Size;
        }
    }
}
